package utils

import (
	"crypto/md5"
	"encoding/hex"
	"fmt"
	"math/rand"
	"os"
	"reflect"
	"regexp"
	"strconv"
	"strings"
	"time"

	"github.com/dgrijalva/jwt-go"
	"github.com/kataras/iris/v12"
)

type EditParam struct {
	Id string `json:"id"`
}

type DelParam struct {
	Ids string `json:"ids"`
}

func CommonRes(code int, msg string, data interface{}) map[string]interface{} {
	if data == "" {
		data = map[string]interface{}{}
	}
	return map[string]interface{}{
		"code":    code,
		"message": msg,
		"data":    data,
	}
}

func PasswordEncode(data string) string {
	return Md5Encode(Md5Encode(data))
}

func Md5Encode(data string) string {
	h := md5.New()
	h.Write([]byte(data))
	return hex.EncodeToString(h.Sum(nil))
}

// 字符串转int64
func Atoi64(a string) int64 {
	i, _ := strconv.ParseInt(a, 10, 64)
	return i
}

// 字符串转int
func Atoi(a string) int {
	n, _ := strconv.Atoi(a)
	return n
}

// 字符串转float64
func Atof64(a string) float64 {
	n, _ := strconv.ParseFloat(a, 64)
	return n
}

func IsMobile(mobile string) bool {
	reg := `^1[3456789]\d{9}$`
	rgx := regexp.MustCompile(reg)
	return rgx.MatchString(mobile)
}

// 生产指定位数的随机数
func GenRandCode(n int) string {
	var codeArr []string
	numArr := []string{"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"}
	rand.Seed(time.Now().UnixNano())
	for i := 0; i < n; i++ {
		codeArr = append(codeArr, numArr[rand.Intn(10)])
	}
	return strings.Join(codeArr, "")
}

// 将手机号中间4位隐藏
func FormatMobile(mobile string) string {
	var arr []string
	for i, m := range mobile {
		if i > 2 && i < 7 {
			arr = append(arr, "*")
		} else {
			arr = append(arr, string(m))
		}
	}
	return strings.Join(arr, "")
}

// 判断是否是身份证号
func IsIdcard(idcard string) bool {
	reg := `^[1-9]\d{7}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}$|^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$`
	rgx := regexp.MustCompile(reg)
	return rgx.MatchString(idcard)
}

// 生成指定位数的随机字符串
func GetRandomString(length int) string {
	str := "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
	bytes := []byte(str)
	var result []byte
	r := rand.New(rand.NewSource(time.Now().UnixNano()))
	for i := 0; i < length; i++ {
		result = append(result, bytes[r.Intn(len(bytes))])
	}
	return string(result)
}

// 生成流水号
func GetSn() string {
	return fmt.Sprintf("%s%s", time.Now().Format("20060102"), strings.ToUpper(GetRandomString(24)))
}

func LogInfo(app *iris.Application, v ...interface{}) {
	app.Logger().Info(v)
}

func LogError(app *iris.Application, v ...interface{}) {
	app.Logger().Error(v)
}

func LogDebug(app *iris.Application, v ...interface{}) {
	app.Logger().Debug(v)
}

func TrimHtml(src string) string {
	//将HTML标签全转换成小写
	re, _ := regexp.Compile("\\<[\\S\\s]+?\\>")
	src = re.ReplaceAllStringFunc(src, strings.ToLower)
	//去除STYLE
	re, _ = regexp.Compile("\\<style[\\S\\s]+?\\</style\\>")
	src = re.ReplaceAllString(src, "")
	//去除SCRIPT
	re, _ = regexp.Compile("\\<script[\\S\\s]+?\\</script\\>")
	src = re.ReplaceAllString(src, "")
	//去除所有尖括号内的HTML代码，并换成换行符
	re, _ = regexp.Compile("\\<[\\S\\s]+?\\>")
	src = re.ReplaceAllString(src, "\n")
	//去除连续的换行符
	re, _ = regexp.Compile("\\s{2,}")
	src = re.ReplaceAllString(src, "\n")
	re, _ = regexp.Compile("&nbsp;")
	src = re.ReplaceAllString(src, "")

	return strings.TrimSpace(src)
}

func Substr(str string, start, length int) string {
	if length == 0 {
		return ""
	}
	rune_str := []rune(str)
	len_str := len(rune_str)

	if start < 0 {
		start = len_str + start
	}
	if start > len_str {
		start = len_str
	}
	end := start + length
	if end > len_str {
		end = len_str
	}
	if length < 0 {
		end = len_str + length
	}
	if start > end {
		start, end = end, start
	}
	return string(rune_str[start:end])
}

func FormatCurDatetime() string {
	return time.Now().Format("2006-01-02 15:04:05")
}

func FormatDatetime(time time.Time) string {
	return time.Format("2006-01-02 03:04:05")
}

func Time(value string) time.Time {
	if t, e := time.Parse("2006-01-02 15:04:05", value); e == nil {
		return t
	} else {
		return time.Now()
	}
}

func IsFolder(path string) bool {
	_, err := os.Stat(path)
	if err == nil {
		return true
	}
	if os.IsNotExist(err) {
		return false
	}
	return false
}

/**
 * 判断数组是否包含某个元素
 */
func InArray(arr interface{}, val interface{}) bool {
	targetValue := reflect.ValueOf(arr)
	switch reflect.TypeOf(arr).Kind() {
	case reflect.Slice, reflect.Array:
		for i := 0; i < targetValue.Len(); i++ {
			if targetValue.Index(i).Interface() == val {
				return true
			}
		}
	case reflect.Map:
		// 匹配的是键值，不是值
		if targetValue.MapIndex(reflect.ValueOf(val)).IsValid() {
			return true
		}
	}
	return false
}

/**
 * 字符串数组去重
 */
func DistinctArrString(arr []string) []string {
	tmpMap := make(map[string]interface{})
	ret := []string{}
	for _, val := range arr {
		if _, ok := tmpMap[val]; !ok && len(strings.TrimSpace(val)) > 0 {
			ret = append(ret, val)
			tmpMap[val] = struct{}{}
		}
	}
	return ret
}

/**
 * string转float
 */
func StringToFloat(str string, bit int) float64 {
	if bit != 32 && bit != 64 {
		bit = 64
	}
	f, _ := strconv.ParseFloat(strings.TrimSpace(str), bit)
	return f
}

/**
 * 将数组转换到url形式字符串
 * @param remove string 需要去除的字符串
 */
func Array2UrlString(arr map[string]string, arr_key []string, remove string) string {
	content := ""
	if len(arr) > 0 && len(arr_key) > 0 {
		for _, v := range arr_key {
			if v != remove {
				content += v + "=" + arr[v] + "&"
			}
		}
		content = content[0 : len(content)-1]
	}
	content = strings.TrimSpace(content)
	return content
}

/**
 * 合并两个map数组
 */
func MergeMap(m1 map[string]interface{}, m2 map[string]interface{}) map[string]interface{} {
	for k, v := range m2 {
		m1[k] = v
	}
	return m1
}

/**
 * 合并两个数组 []string
 */
func MergeString(s ...[]string) []string {
	switch len(s) {
	case 0:
		return []string{}
	case 1:
		return s[0]
	default:
		var str []string
		str = append(s[0], s[1]...)
		return str
	}
}

func Contains(slice []string, item string) bool {
	set := make(map[string]struct{}, len(slice))
	for _, s := range slice {
		set[s] = struct{}{}
	}

	_, ok := set[item]
	return ok
}

func ContainsInt64(slice []int64, item int64) bool {
	set := make(map[int64]struct{}, len(slice))
	for _, s := range slice {
		set[s] = struct{}{}
	}
	_, ok := set[item]
	return ok
}

func RemoveDuplicatesAndEmpty(a []string) (ret []string) {
	a_len := len(a)
	for i := 0; i < a_len; i++ {
		if (i > 0 && a[i-1] == a[i]) || len(a[i]) == 0 {
			continue
		}
		ret = append(ret, a[i])
	}
	return
}

/***********************Token**************************/

//生成token
var jwtSecret = []byte("baokaobang")

type Claims struct {
	Username string `json:username`
	Password string `json:password`
	jwt.StandardClaims
}

//生成token
func GenerateToken(username, password, id string) (string, error) {
	nowTime := time.Now()
	expireTime := nowTime.Add(8760 * time.Hour)

	claims := Claims{
		username,
		password,

		jwt.StandardClaims{
			ExpiresAt: expireTime.Unix(),
			Id:        id,
		},
	}

	tokenClaims := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
	token, err := tokenClaims.SignedString(jwtSecret)

	return token, err
}

//解析token
func ParseToken(token string) (*Claims, error) {

	tokenClaims, err := jwt.ParseWithClaims(token, &Claims{}, func(token *jwt.Token) (interface{}, error) {
		return jwtSecret, nil
	})

	if tokenClaims != nil {
		if claims, ok := tokenClaims.Claims.(*Claims); ok && tokenClaims.Valid {
			return claims, nil
		}
	}

	return nil, err
}
